package code07_面向对象.封装;

/**
 * @author 黄衡熙
 * @version 1.0
 * @date 2025年07月21日19:00
 */
public class Poker {
    private Card[] cards;

    public Card[] getCards() {
        return cards;
    }

    public void setCards(Card[] cards) {
        this.cards = cards;
    }

    /**
     * 定义Poker的构造方法,为一副牌填充54张牌
     */
    public Poker() {
        // 在此处为一副扑克牌填充54张牌
        cards = new Card[54];
        // 定义扑克牌花色的范围
        String[] colors = {"黑桃", "梅花", "红桃", "方块"};
        // 定义牌的点数的范围
        String[] nums = {"A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"};

        // 通过双重for循环,将每一种花色与每一个点数进行组合
        // 共有4*13=52张牌
        // 定义cards的初始下标
        int index = 0;
        for (String color : colors) {
            for (String num : nums) {
                cards[index++] = new Card(color, num);
            }
        }

        // 除外上述52张牌以外,还有大小王,共54张牌
        cards[index++] = new Card("大", "王 ");
        cards[index++] = new Card("小", "王 ");
    }

    /**
     * 洗牌方法
     * 创建一个洗牌方法shuffle,将牌的顺序打乱后展示
     * 备注:创建一个新的数组,向该数组中填充元素,元素的来源为未洗牌前的数组
     * 最终将洗牌后的新数组赋值给属性
     */
    public void shuffle() {
        // 定义一个相同长度,相同类型的数组
        Card[] cards = new Card[54];
        // 未洗牌前的数组中已经存在了一副牌的扑克了
        // 因此,我们可以随机从未洗牌前的数组中获取元素,共获取54次
        for (int i = 0; i < cards.length; i++) {
            // 获取0-53的随机数,作为获取洗牌前数组的下标
            int index = (int) (Math.random() * 54);
            // 取出对应下标的元素
            Card card = this.cards[index];

            // 随机获取的元素在新的数组中可能已经存在了
            // 而一副扑克牌中不存在重复的牌
            // 如果再次使用一个内层循环判断,那么循环次数就会非常的多
            // 可以将未洗牌的数组中已经获取过的元素的值赋值为null
            while (card == null) {
                // 只要当前获取的元素的值为null,那么就说明该位置的牌已经取过了
                // 因此,需要重新循环一次
                index = (int) (Math.random() * 54);
                card = this.cards[index];
            }

            // 将取出的元素赋值给新的数组
            cards[i] = card;
            // 将未洗牌前的数组中元素的值设置为null
            this.cards[index] = null;
        }
        this.cards = cards;
    }
}
